package tm.testing;

import com.jme.math.Vector3f;
import com.jme.scene.Node;

public class MapGrid {
	
	//The MapGrid size is currently set to 8.75cm real equals 1 in-game unit
	//e.g. needed 7m -> 700cm / 8.75 = 80 in-game units
	
	private static Node node;
	private static int gridSize;
	private static int elementAmount;
	private GridElement[] gridElements;
	private static int x1coord;
	private static int y1coord;
	public float defaultHeight = 127.0f;
	
	public MapGrid(int gS, int gridTiling, Node n) {
		node = n;
		gridSize = gS;
		elementAmount = gridTiling*gridTiling;
		gridElements = new GridElement[elementAmount];
		this.defaultHeight = 127.0f; 
		
		//Calculate the x and y coordinate of the center of GridElement(1|1)
		x1coord = (int) ((0-(gridSize/2))-(((Math.sqrt(elementAmount)/2)-1)*gridSize));
		y1coord = (int) ((0+(gridSize/2))+(((Math.sqrt(elementAmount)/2)-1)*gridSize));
		
		generateEmptyElements();
	}
	
	public boolean isValidCoordinate(Coordinate c) {
		if(c.getX()>0 && c.getX()<Math.sqrt(elementAmount) && c.getY()>0 && c.getY()<Math.sqrt(elementAmount)) {
			return true;
		} else {
			return false;
		}
	}
	
	
	
	
	private void generateEmptyElements() {
		int i = 0;
		int x = 1;
		for(; x <= Math.sqrt(elementAmount); x++) {
			int y = 1;
			for(; y <= Math.sqrt(elementAmount); y++) {
				gridElements[i] = new GridElement(x,y);
				node.attachChild(gridElements[i]);
				i++;
			}
		}
	}
	
	public GridElement getGridElement(int x, int y)
	throws MapElementIndexOutOfBoundsException {
		//Calculate the index of the given GridElement(x,y) and return
		
		if(x > Math.sqrt(elementAmount) || y > Math.sqrt(elementAmount)) {
			throw new MapElementIndexOutOfBoundsException();
		}

		
		int index = (int) ((elementAmount-1)-(((Math.sqrt(elementAmount)-x)*Math.sqrt(elementAmount))+(Math.sqrt(elementAmount)-y)));
		return gridElements[index];
	}
	
	
	public Vector3f getElementCoord(int x, int y, float height)
	throws MapElementIndexOutOfBoundsException {
		if(x > Math.sqrt(elementAmount) || y > Math.sqrt(elementAmount)) {
			throw new MapElementIndexOutOfBoundsException();
		}
		
		int xn = x1coord;
		if(x!=1) {
			xn= x1coord+((x-1)*gridSize);
		}
		int yn = y1coord;
		if(y!=1) {
			yn = y1coord-((y-1)*gridSize);
		}
		
		
		return new Vector3f(xn,height,yn);
	}
	
	
	public Coordinate getGridIndex(Vector3f v) {
		int x = -1;
		int y = -1;
		
		//Compute x value of the result coordinate
		if(v.getX() > 0) {
			double tmp = (Math.floor((v.getX()/gridSize)));
			x = (int) (Math.sqrt(elementAmount)-((Math.sqrt(elementAmount)/2)+(tmp+1)))+1;
		} else {
			double tmp = (Math.floor((v.getX()/gridSize)));
			x = (int) (Math.sqrt(elementAmount)-((Math.sqrt(elementAmount)/2)+(tmp)))+1;
		}
		
		//Compute y value of the result coordinate
		if(v.getZ() > 0) {
			double tmp = (Math.floor((v.getZ()/gridSize)));
			y = (int) (Math.sqrt(elementAmount)-((Math.sqrt(elementAmount)/2)+(tmp+1)))+1;
		} else {
			double tmp = (Math.floor((v.getZ()/gridSize)));
			y = (int) (Math.sqrt(elementAmount)-((Math.sqrt(elementAmount)/2)+(tmp)))+1;			
		}
		
		
		// TODO There is an error in the code above. Grid index 32 is followed by 34 NOT 33.
		//		Actually I don't know the reason know, but there is a simple workaround tough.
		//		If a grid index is above 32 it gets reduced by 1 so 34->33, 35->34, 65->64 and
		//		so on. This should work for the moment, however this is NOT a smart solution
		//		and should be fixed before release!
		if(x>32) {
			x -= 1;
		}
		if(y>32) {
			y -= 1;
		}
		
		// TODO This method even more fucked up as I thought above. Actually where should be 1,1 is
		//		64,1 so the x value is mirrored. I don't have the time to work this out know so here
		//		is my next little workaround:
		x = (x-((int)Math.sqrt(elementAmount))-1) * (-1);
		
		
		
		return new Coordinate(x, y);
		
	}
	
	
}
